package com.seven.first.config;


import com.seven.first.dto.ExampleUserInfoDTO;
import com.seven.first.po.ExampleUserInfoPO;
import com.seven.first.suite.util.DateUtil;
import com.seven.first.suite.util.LocalDateUtil;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.MappingContext;
import ma.glasnost.orika.converter.BidirectionalConverter;
import ma.glasnost.orika.converter.ConverterFactory;
import ma.glasnost.orika.metadata.Type;
import org.springframework.context.annotation.Configuration;
import net.rakugakibox.spring.boot.orika.*;
import java.time.LocalDateTime;
import java.util.Date;


/**
 * @author seven
 */
@Configuration
public class OrikaConfiguration implements OrikaMapperFactoryConfigurer{

    @Override
    public void configure(MapperFactory factory) {
        this.registerConverter(factory);
        this.registerMap(factory);
    }

    /**
     * 一对类中两个字段的映射，按例子中的方式，可以自定义映射，可以自定义多个类的映射
     * @param factory
     */
    private void registerMap(MapperFactory factory) {
        factory.classMap(ExampleUserInfoPO.class, ExampleUserInfoDTO.class)
//                .fieldMap("id", "id").converter("Str2Long").add()
                .fieldMap("createdTime", "createdTime").converter("Str2Date").add()
                .byDefault().register();
    }

    /**
     * 注册转换器，给转换器注册一个名字，使用时用名字就可以了
     * @param factory
     */
    private void registerConverter(MapperFactory factory) {
        ConverterFactory converterFactory = factory.getConverterFactory();
        converterFactory.registerConverter("PageNum", new PageNum());
        converterFactory.registerConverter("Str2LocalDateTime", new Str2LocalDateTime());
        converterFactory.registerConverter("Str2Date", new Str2Date());
        converterFactory.registerConverter("Str2Long", new Str2Long());
        converterFactory.registerConverter("Str2str", new Str2Str());
    }

    /**
     * 字符串转日期
     */
    private class PageNum extends BidirectionalConverter<Integer, Integer> {
        @Override
        public Integer convertTo(Integer source, Type<Integer> destinationType, MappingContext mappingContext) {
            return source;
        }

        @Override
        public Integer convertFrom(Integer source, Type<Integer> destinationType, MappingContext mappingContext) {
            return source;
        }
    }

    private class Str2LocalDateTime extends BidirectionalConverter<String, LocalDateTime> {
        @Override
        public LocalDateTime convertTo(String source, Type<LocalDateTime> destinationType, MappingContext mappingContext) {
            return LocalDateUtil.parseyyyyMMddHHmmss(source);
        }

        @Override
        public String convertFrom(LocalDateTime source, Type<String> destinationType, MappingContext mappingContext) {
            return LocalDateUtil.formatyyyyMMddHHmmss(source);
        }
    }

    private class Str2Date extends BidirectionalConverter<String, Date> {

        @Override
        public Date convertTo(String source, Type<Date> destinationType, MappingContext mappingContext) {
            return DateUtil.parse(source);
        }

        @Override
        public String convertFrom(Date source, Type<String> destinationType, MappingContext mappingContext) {
            return DateUtil.format(source);
        }
    }

    private class Str2Long extends BidirectionalConverter<String, Long> {
        @Override
        public Long convertTo(String source, Type<Long> destinationType, MappingContext mappingContext) {
            return Long.parseLong(source);
        }

        @Override
        public String convertFrom(Long source, Type<String> destinationType, MappingContext mappingContext) {
            return Long.toString(source);
        }
    }



    private class Str2Str extends BidirectionalConverter<String, String> {
        @Override
        public String convertTo(String source, Type<String> destinationType, MappingContext mappingContext) {
            return source;
        }

        @Override
        public String convertFrom(String source, Type<String> destinationType, MappingContext mappingContext) {
            return source;
        }
    }


}
